#include <iostream>
#include <cmath>
#include <fstream>
#include <iomanip>
#include <vector>
#include <string>
using namespace std;

int startnum = 0;

// 结构体
struct zuobiao
{
    double mile;
    double X;
    double Y;
};

zuobiao JD = {14906.807, 144534.846, 99482.202};

// 得到角度转换参数
double phi = atan(1) * 4;

// 已知数据
double R = 700, L_s = 100, a = 66.0 + 1.0 / 60 + 15.0 / 3600;
double h_a = a * phi / 180.0;
double jiao_zh_jd = 273 + 15.0 / 60 + 23.4 / 3600;
double jiao_hz = jiao_zh_jd + a - 180;

// 定义重要点坐标
zuobiao ZH, HY, QZ, YH, HZ;

void get_values(double *m, double *P, double *beta, double *T_h, double *L_h, double *E_h, double *q)
{
    *m = L_s / 2 - pow(L_s, 3) / (240 * pow(R, 2));
    *P = pow(L_s, 2) / (24 * R);
    *beta = L_s * 180 / (phi * 2 * R);

    *T_h = (R + *P) * tan(h_a / 2) + *m;
    *L_h = (phi * R / 180) * (a - 2 * *beta) + 2 * L_s;
    *E_h = (R + *P) / cos(h_a / 2) - R;
    *q = 2 * *T_h - *L_h;
}

double get_mile(zuobiao *ZH, zuobiao *HY, zuobiao *QZ, zuobiao *YH, zuobiao *HZ, zuobiao *JD, double *T_h, double *L_h, double *beta)
{
    (*ZH).mile = (*JD).mile - *T_h;
    (*HY).mile = (*ZH).mile + L_s;
    (*QZ).mile = (*ZH).mile + *L_h / 2;

    double L_T = R * (a - 2 * *beta) * phi / 180;
    (*YH).mile = (*HY).mile + L_T;
    (*HZ).mile = (*YH).mile + L_s;

    return L_T;
}

void test_value(double t1, double t2)
{
    if (t1 == t2)
    {
        cout << "检验结果正确一致！" << endl;
        cout << t1 << " = " << t2 << endl;
    }
    else
        cout << "false" << endl;
}

// 第一段缓直线
void get_XY1(zuobiao *data, double K_zh, int num)
{
    double L1_i = 0;
    ZH.X = L1_i - pow(L1_i, 5) / (40 * pow(R, 2) * pow(L_s, 2));
    ZH.Y = pow(L1_i, 3) / (6 * R * L_s);
    for (int i = 0; i < num; i++)
    {
        double s = 10 * (i + 1);
        data[i].mile = int(K_zh / 10) * 10 + s;
        double L_i = data[i].mile - ZH.mile;
        data[i].X = L_i - pow(L_i, 5) / (40 * pow(R, 2) * pow(L_s, 2));
        data[i].Y = pow(L_i, 3) / (6 * R * L_s);
    }
}

// 第二段圆曲线
void get_XY2(zuobiao *data, double HYs, int num, double ZH, double m, double q)
{
    double P = pow(L_s, 2) / (24 * R);

    double L1_i = HYs;
    double l1_i = L1_i - ZH;
    double jiao1 = (l1_i - 0.5 * L_s) * 180 / (phi * R);
    HY.X = double(m + R * sin(jiao1 * phi / 180));
    HY.Y = double(P + R * (1 - cos(jiao1 * phi / 180)));

    double L2_i = QZ.mile;
    double l2_i = L2_i - ZH;
    double jiao2 = (l2_i - 0.5 * L_s) * 180 / (phi * R);
    QZ.X = double(m + R * sin(jiao2 * phi / 180));
    QZ.Y = double(P + R * (1 - cos(jiao2 * phi / 180)));

    double L3_i = YH.mile;
    double l3_i = L3_i - ZH;
    double jiao3 = (l3_i - 0.5 * L_s) * 180 / (phi * R);
    YH.X = double(m + R * sin(jiao3 * phi / 180));
    YH.Y = double(P + R * (1 - cos(jiao3 * phi / 180)));

    for (int i = 0; i < num; i++)
    {
        double L_i = 10 * (i + 1) + int(HYs / 10) * 10;
        data[i].mile = L_i;

        double l_i = L_i - ZH;
        double jiao = (l_i - 0.5 * L_s) * 180 / (phi * R);

        data[i].X = m + R * sin(jiao * phi / 180);
        data[i].Y = P + R * (1 - cos(jiao * phi / 180));
    }
}

void get_XY3(zuobiao *data, double K_zh, int num)
{
    // double K_i1 = YH.mile;
    // double L1_i = HZ.mile - K_i1;
    // YH.X = L1_i - pow(L1_i, 5) / (40 * pow(R, 2) * pow(L_s, 2));
    // YH.Y = pow(L1_i, 3) / (6 * R * L_s);

    double K_i2 = HZ.mile;
    double L2_i = HZ.mile - K_i2;
    HZ.X = L2_i - pow(L2_i, 5) / (40 * pow(R, 2) * pow(L_s, 2));
    HZ.Y = pow(L2_i, 3) / (6 * R * L_s);

    for (int i = 0; i < num; i++)
    {
        double K_i = int(YH.mile / 10) * 10 + 10 * (i + 1);
        double L_i = HZ.mile - K_i;
        data[i].mile = K_i;
        data[i].X = L_i - pow(L_i, 5) / (40 * pow(R, 2) * pow(L_s, 2));
        data[i].Y = pow(L_i, 3) / (6 * R * L_s);
    }
}

// 坐标变换
void change_get_XY(double T)
{
    ZH.X = JD.X - T * cos(jiao_zh_jd * phi / 180);
    ZH.Y = JD.Y - T * sin(jiao_zh_jd * phi / 180);
    HZ.X = JD.X - T * cos(jiao_hz * phi / 180);
    HZ.Y = JD.Y - T * sin(jiao_hz * phi / 180);
}
// ZH-HY曲线上
void change_get_XY1(zuobiao *data, int num)
{
    for (int i = 0; i < num; i++)
    {
        double X = ZH.X + data[i].X * cos(jiao_zh_jd * phi / 180) - data[i].Y * sin(jiao_zh_jd * phi / 180);
        double Y = ZH.Y + data[i].X * sin(jiao_zh_jd * phi / 180) + data[i].Y * cos(jiao_zh_jd * phi / 180);
        data[i].X = X;
        data[i].Y = Y;
    }
}
// HY-HZ曲线上
void change_get_XY2(zuobiao *data, int num)
{
    for (int i = 0; i < num; i++)
    {
        double X = HZ.X + data[i].X * cos(jiao_hz * phi / 180) + data[i].Y * sin(jiao_hz * phi / 180);
        double Y = HZ.Y + data[i].X * sin(jiao_hz * phi / 180) - data[i].Y * cos(jiao_hz * phi / 180);
        data[i].X = X;
        data[i].Y = Y;
    }
}

// 展示数据
void show(double T_h, double L_h, double E_h, double q)
{
    fstream file;
    file.open("datas.txt", ios::out);
    file << "刘维康 2022302141211" << endl;
    file << "-----------------------------------------------------" << endl;
    cout << "刘维康 2022302141211" << endl;
    cout << "-----------------------------------------------------" << endl;
    if (!file)
    {
        std::cerr << "Unable to open file!" << std::endl;
        // 文件打开失败
    }
    file << "曲线综合要素:" << endl;
    file << "切线长T: " << T_h << "       曲线长L: " << L_h << endl;
    file << "外矢距E0: " << E_h << "      切曲差：" << q << endl;
    file << endl;
    file << setw(4) << "主点" << right << setw(12) << "里程" << setw(13) << "X" << setw(13) << "Y" << endl;
    cout << "曲线综合要素:" << endl;
    cout << "切线长T: " << T_h << "       曲线长L: " << L_h << endl;
    cout << "外矢距E0: " << E_h << "      切曲差：" << q << endl;
    cout << endl;
    cout << setw(4) << "主点" << right << setw(12) << "里程" << setw(13) << "X" << setw(13) << "Y" << endl;
    file.close();
}

void show_jiaomi()
{

    fstream file;
    file.open("datas.txt", ios::app);

    file << endl;
    cout << setw(3) << "加密" << right << setw(12) << "里程" << setw(13) << "X" << setw(13) << "Y" << endl;
    file << setw(3) << "加密" << right << setw(12) << "里程" << setw(13) << "X" << setw(13) << "Y" << endl;
    file.close();
}

string zhudian_id[] = {"ZH", "HY", "QZ", "YH", "HZ"};
int zhudian_start = 0;

void show_XY1(zuobiao *data, int len)
{

    fstream file;
    file.open("datas.txt", ios::app);

    for (int i = 0; i < len; i++)
    {
        string s_id;
        int k = int(data[i].mile / 1000);
        double s = data[i].mile - k * 1000;
        string str = "DK" + to_string(k) + "+ ";
        if (len != 1)
        {
            startnum++;
            s_id = to_string(startnum);
        }
        else
        {
            s_id = zhudian_id[zhudian_start];
            zhudian_start++;
        }
        cout << setw(3) << s_id << setw(10) << setiosflags(ios::fixed) << setprecision(3) << str << setw(7) << setiosflags(ios::fixed) << setprecision(3) << s << "   " << data[i].X << "   " << data[i].Y << endl;
        file << setw(3) << s_id << setw(10) << setiosflags(ios::fixed) << setprecision(3) << str << setw(7) << setiosflags(ios::fixed) << setprecision(3) << s << "   " << data[i].X << "   " << data[i].Y << endl;
    }
    file.close();
}
